home *** CD-ROM | disk | FTP | other *** search
- /* SCCS Id: @(#)winmenu.c 3.1 92/3/7
- /* Copyright (c) Dean Luick, 1992 */
- /* NetHack may be freely redistributed. See license for details. */
-
- /*
- * File for creating menus.
- *
- * + Global functions: start_menu, add_menu, end_menu, select_menu
- */
- #include <X11/Intrinsic.h>
- #include <X11/StringDefs.h>
- #include <X11/Shell.h>
- #include <X11/Xaw/List.h>
- #include <X11/Xaw/Viewport.h>
- #include <X11/Xaw/Cardinals.h>
-
- #include "hack.h"
- #include "winX.h"
-
-
- static void clear_old_menu();
- static char *copy_of();
-
- #define check_menu(func_name) \
- { \
- if (!menu_info->is_menu) { \
- impossible("%s: called before start_menu", func_name); \
- return; \
- } \
- }
-
- static char menu_selected; /* selected menu item */
- static const char menu_translations[] =
- "#override\n\
- <Key>: menu_key()";
-
- /*
- * Menu callback.
- */
- /* ARGSUSED */
- static void
- menu_select(w, client_data, call_data)
- Widget w;
- XtPointer client_data, call_data;
- {
- XawListReturnStruct *lrs = (XawListReturnStruct *) call_data;
- int i;
- struct menu_info_t *menu_info;
- struct menu_item *curr;
- struct xwindow *wp;
-
- wp = find_widget(w);
- menu_info = wp->menu_information;
-
- for (i = 0, curr = menu_info->base; i < lrs->list_index; i++) {
- if (!curr) panic("menu_select: out of menu items!");
- curr = curr->next;
- }
-
- /* If we don't have a selector, try again. */
- if (!curr->selector) {
- XawListUnhighlight(w); /* unhilight non-menu item */
- X11_nhbell();
- return;
- }
- menu_selected = curr->selector;
-
- nh_XtPopdown(wp->popup); /* this removes the event grab */
- exit_x_event = TRUE; /* exit our event handler */
- }
-
- /*
- * Called when we get a key press event on a menu window.
- */
- /* ARGSUSED */
- void
- menu_key(w, event, params, num_params)
- Widget w;
- XEvent *event;
- String *params;
- Cardinal *num_params;
- {
- struct menu_info_t *menu_info;
- struct menu_item *curr;
- struct xwindow *wp;
- char ch;
- int count;
-
- wp = find_widget(w);
- menu_info = wp->menu_information;
-
- ch = key_event_to_char((XKeyEvent *) event);
-
- if (ch == '\0') { /* don't accept nul char/modifier event */
- /* don't beep */
- return;
- }
-
- for (count = 0, curr = menu_info->base; curr; curr = curr->next, count++)
- if (curr->selector == ch) break;
-
- if (curr) {
- XawListHighlight(w, count); /* highlit item */
- menu_selected = ch;
- } else if (menu_info->other_valid && index(menu_info->other_valid, ch)) {
- menu_selected = menu_info->other_response;
- } else {
- X11_nhbell(); /* no match */
- return;
- }
-
- nh_XtPopdown(wp->popup); /* this removes the event grab */
- exit_x_event = TRUE; /* exit our event handler */
- }
-
-
- /* Global functions ======================================================== */
-
- void
- X11_start_menu(window)
- winid window;
- {
- struct xwindow *wp;
- check_winid(window);
-
- wp = &window_list[window];
-
- if (wp->menu_information->is_menu) {
- /* clear old menu and widgets (if any) */
- clear_old_menu(wp);
- } else {
- wp->menu_information->is_menu = TRUE;
- }
- }
-
- void
- X11_add_menu(window, ch, attr, str)
- winid window;
- char ch;
- int attr;
- const char *str;
- {
- struct menu_item *item;
- struct menu_info_t *menu_info;
-
- check_winid(window);
- menu_info = window_list[window].menu_information;
- check_menu("add_menu");
-
- item = (struct menu_item *) alloc((unsigned)sizeof(struct menu_item));
- item->next = (struct menu_item *) 0;
- item->selector = ch;
- item->attr = attr;
- item->str = copy_of(str);
-
- if (menu_info->last) {
- menu_info->last->next = item;
- } else {
- menu_info->base = item;
- }
- menu_info->last = item;
- menu_info->count++;
- }
-
- void
- X11_end_menu(window, cancel_ch, cancel_str, morestr)
- winid window;
- char cancel_ch;
- const char *cancel_str;
- const char *morestr;
- {
- struct menu_info_t *menu_info;
- check_winid(window);
- menu_info = window_list[window].menu_information;
- check_menu("end_menu");
-
- if(morestr && strlen(morestr))
- X11_add_menu(window, 0, 0, morestr);
- menu_info->other_valid = cancel_str;
- menu_info->other_response = cancel_ch;
- menu_info->query = morestr;
- }
-
- char
- X11_select_menu(window)
- winid window;
- {
- struct menu_item *curr;
- struct xwindow *wp;
- struct menu_info_t *menu_info;
- Arg args[8];
- Cardinal num_args;
- String *ptr;
- int i;
- Widget viewport_widget;
- Dimension pixel_height, top_margin, spacing;
- XFontStruct *fs;
-
- check_winid(window);
- wp = &window_list[window];
- menu_info = wp->menu_information;
-
- #if defined(LINT) || defined(GCC_WARN)
- {
- /* cannot use check_menu, since it doesn't return anything */
- if (!menu_info->is_menu) {
- impossible("%s: called before start_menu", "select_menu");
- return '\0';
- }
- }
- #else
- check_menu("select_menu");
- #endif
-
- #ifdef VERBOSE
- /* ********** */
- if (menu_info->other_valid) {
- char *cp;
- printf("select_menu: other_valid = \"");
- for (cp = menu_info->other_valid; *cp; cp++) {
- if (*cp < 32) {
- printf("^%c", '@' + *cp);
- } else
- printf("%c", *cp);
- }
- printf("\"\n");
- } else {
- printf("select_menu: other_valid = NULL\n");
- }
- if (menu_info->other_response < 32) {
- printf("select_menu: other_response = '^%c'\n",
- '@' + menu_info->other_response);
- } else {
- printf("select_menu: other_response = '%c'\n",
- menu_info->other_response);
- }
- if (menu_info->query) {
- printf("select_menu: query = \"%s\"\n", menu_info->query);
- } else {
- printf("select_menu: query = NULL\n");
- }
- /* ********** */
- #endif
-
- num_args = 0;
- XtSetArg(args[num_args], XtNallowShellResize, True); num_args++;
-
- wp->popup = XtCreatePopupShell("menu", transientShellWidgetClass,
- toplevel, args, num_args);
-
- menu_info->list_pointer =
- (String *) alloc((unsigned) (sizeof(String) * (menu_info->count+1)));
- for (i = 0, ptr = menu_info->list_pointer, curr = menu_info->base;
- i < menu_info->count; i++, ptr++, curr = curr->next) {
- *ptr = (String) curr->str;
- }
- *ptr = (String) 0;
-
- num_args = 0;
- XtSetArg(args[num_args], XtNallowVert, True); num_args++;
-
- viewport_widget = XtCreateManagedWidget(
- "menu_viewport", /* name */
- viewportWidgetClass,
- wp->popup, /* parent widget */
- args, num_args); /* values, and number of values */
-
- num_args = 0;
- XtSetArg(args[num_args], XtNforceColumns, True); num_args++;
- XtSetArg(args[num_args], XtNdefaultColumns, 1); num_args++;
- XtSetArg(args[num_args], XtNlist, menu_info->list_pointer); num_args++;
- XtSetArg(args[num_args], XtNtranslations,
- XtParseTranslationTable(menu_translations)); num_args++;
-
- wp->w = XtCreateManagedWidget(
- "menu_list", /* name */
- listWidgetClass,
- viewport_widget, /* parent widget */
- args, /* set some values */
- num_args); /* number of values to set */
-
- XtAddCallback(wp->w, XtNcallback, menu_select, (XtPointer) 0);
-
- menu_info->valid_widgets = TRUE;
-
- /* Get the font and margin information. */
- num_args = 0;
- XtSetArg(args[num_args], XtNfont, &fs); num_args++;
- XtSetArg(args[num_args], XtNinternalHeight, &top_margin); num_args++;
- XtSetArg(args[num_args], XtNrowSpacing, &spacing); num_args++;
- XtGetValues(wp->w, args, num_args);
-
- /* font height is ascent + descent */
- pixel_height = top_margin +
- ((menu_info->count + 4) *
- (fs->max_bounds.ascent + fs->max_bounds.descent + spacing));
-
- /* if viewport will be bigger than the screen, limit its height */
- if ((Dimension) XtScreen(wp->w)->height <= pixel_height) {
- pixel_height = XtScreen(wp->w)->height / 2;
-
- num_args = 0;
- XtSetArg(args[num_args], XtNheight, pixel_height); num_args++;
- XtSetValues(viewport_widget, args, num_args);
- }
-
- XtRealizeWidget(wp->popup); /* need to realize before we position */
- positionpopup(wp->popup);
-
- menu_selected = '\0';
-
- nh_XtPopup(wp->popup, XtGrabExclusive, wp->w);
- (void) x_event(EXIT_ON_EXIT);
-
- return menu_selected;
- }
-
- /* End global functions ==================================================== */
-
- static char *
- copy_of(s)
- char *s;
- {
- char *copy;
- if (s) {
- copy = (char *) alloc((unsigned) (strlen(s)+1));
- Strcpy(copy,s);
- } else {
- copy = (char *) alloc((unsigned) 1);
- *copy = '\0';
- }
-
- return copy;
- }
-
- static void
- clear_old_menu(wp)
- struct xwindow *wp;
- {
- struct menu_info_t *menu_info = wp->menu_information;
-
- while (menu_info->base) {
- menu_info->last = menu_info->base;
- menu_info->base = menu_info->base->next;
-
- free(menu_info->last->str);
- free((char *)menu_info->last);
- }
- menu_info->last = (struct menu_item *) 0;
- menu_info->other_valid = (char *) 0;
- menu_info->other_response = '\0';
- menu_info->query = (char *) 0;
- menu_info->count = 0;
-
- if (menu_info->valid_widgets) {
- nh_XtPopdown(wp->popup);
- XtDestroyWidget(wp->popup);
- menu_info->valid_widgets = FALSE;
- free((char *) menu_info->list_pointer);
- }
- }
-
- void
- create_menu_window(wp)
- struct xwindow *wp;
- {
- struct menu_info_t *menu_info;
-
- wp->type = NHW_MENU;
-
- wp->menu_information = menu_info =
- (struct menu_info_t *) alloc(sizeof(struct menu_info_t));
-
- menu_info->base = (struct menu_item *) 0;
- menu_info->last = (struct menu_item *) 0;
- menu_info->query = (char *) 0;
- menu_info->other_valid = (char *) 0;
- menu_info->other_response = '\0';
- menu_info->count = 0;
- menu_info->list_pointer = (String *) 0;
- menu_info->valid_widgets = FALSE;
- wp->w = wp->popup = (Widget) 0;
- menu_info->is_menu = FALSE;
- }
-
- void
- destroy_menu_window(wp)
- struct xwindow *wp;
- {
- /* printf("destroy_menu_window\n"); */
-
- clear_old_menu(wp); /* this will also destroy the widgets */
- free((char *) wp->menu_information);
-
- wp->type = NHW_NONE; /* allow re-use */
- }
-
-
-